﻿using LightCAD.Core.Elements;
using System.Collections.ObjectModel;
using System.Linq;

namespace LightCAD.Core
{
    public class LcAxisGrid : LcGroup
    {
        //private LcAxisLineCollection axisLines;

        public LcAxisGrid()
        {
            this.Type = BuiltinElementType.AxisGrid;
            //AxisLines = new LcAxisLineCollection();
            crossVectorPoints = null;
        }
        public static double offValue => 1000;
        private Vector2 basePoint;
        public Vector2 BasePoint
        {

            get { return basePoint; }
            set
            {
                if (basePoint != null)
                {
                    for (int i = 0; i < this.Elements.Count; i++)
                    {
                        var element = this.Elements[i];
                        var mat = Matrix3.GetTranslate(basePoint.Clone().Add(new Vector2(-offValue, -offValue)));
                        element = element.ApplyMatrix(mat.Invert());
                    }
                }

                basePoint = value;
                for (int i = 0; i < this.Elements.Count; i++)
                {
                    var element = this.Elements[i];
                    var mat = Matrix3.GetTranslate(basePoint.Clone().Add(new Vector2(-offValue, -offValue)));
                    element = element.ApplyMatrix(mat);
                }

            }
        }
        public string StyleName { get; set; }
        public string RatioName { get; set; }
        //public LcAxisLineCollection AxisLines { get; set; }
        public double SumWidth { get; set; }
        public double SumHeight { get; set; }

        public override LcElement Clone()
        {
            throw new NotImplementedException();
        }
        private List<Vector2> crossVectorPoints;
        public List<Vector2> CrossVectorPoints
        {
            get
            {
                if (crossVectorPoints == null)
                {
                    crossVectorPoints = new List<Vector2>();
                    foreach (LcAxisLine lcAxisLine in this.Elements)
                    {
                        foreach (LcAxisLine lcAxisLine2 in this.Elements)
                        {
                            if (lcAxisLine == lcAxisLine2)
                            {
                                continue;
                            }
                            LcLine line2D = lcAxisLine2.AxisLine;
                            if (line2D != null)
                            {
                                Vector2 vector2 = lcAxisLine.LineCrossLine(line2D);
                                if (!double.IsNaN(vector2.X) && !double.IsNaN(vector2.Y))
                                {
                                    crossVectorPoints.Add(vector2);
                                }
                            }
                        }
                    }
                }
                return crossVectorPoints;
            }
        }
        public override Box2 GetBoundingBox()
        {
            var box = Box2.Empty;
            foreach (var ele in this.Elements)
            {
                box.Union(ele.GetBoundingBox());
            }
            return box;
        }
        public override Box2 GetBoundingBox(Matrix3 matrix)
        {
            var box = Box2.Empty;
            foreach (var ele in this.Elements)
            {
                box.Union(ele.GetBoundingBox(matrix));
            }
            return box;
        }
        public override bool IntersectWithBox(Polygon2d testPoly, List<RefChildElement> intersectChildren = null)
        {
            Box2 thisBox = this.BoundingBox;
            if (!thisBox.IntersectsBox(testPoly.BoundingBox))
            {
                return false;
            }

            foreach (var ele in this.Elements)
            {
                if (intersectChildren == null)
                {
                    //如果不计算子元素相交，任意子元素相交，则本元素相交
                    if (ele.IntersectWithBox(testPoly))
                    {
                        return true;
                    }
                }
            }
            if (intersectChildren == null) return false;
            //任意子元素被相交，则元素被相交
            return intersectChildren.Count > 0;
        }

        public override bool IncludedByBox(Polygon2d testPoly, List<RefChildElement> includedChildren = null)
        {
            Box2 thisBox = this.BoundingBox;
            if (!thisBox.IntersectsBox(testPoly.BoundingBox))
            {
                return false;
            }
            foreach (var ele in this.Elements)
            {
                if (includedChildren == null)
                {
                    //如果不需要计算子元素包含情况，有一个子元素没包含，则本元素不被包含
                    if (!ele.IncludedByBox(testPoly))
                    {
                        return false;
                    }
                }
            }
            if (includedChildren == null) return true;
            //所有子元素都被包含，则本元素被包含
            return includedChildren.Count == this.Elements.Count;
        }


        public void Set(Vector2 basePoint = null, bool fireChangedEvent = true)
        {
            //PropertySetter:Start,End
            if (!fireChangedEvent)
            {
                if (basePoint != null) this.BasePoint = basePoint;
            }
            else
            {
                bool chg_start = (basePoint != null && basePoint != this.BasePoint);
                if (chg_start)
                {
                    OnPropertyChangedBefore(nameof(this.BasePoint), this.BasePoint, basePoint);
                    var oldValue = this.BasePoint;
                    this.BasePoint = basePoint;
                    OnPropertyChangedAfter(nameof(this.BasePoint), oldValue, this.BasePoint);
                }
            }
            crossVectorPoints = null;
        }


        public override void WriteProperties(Utf8JsonWriter writer, JsonSerializerOptions soptions)
        {
            base.WriteProperties(writer, soptions);
            writer.WriteVector2dProperty(nameof(BasePoint), this.BasePoint);
            writer.WriteStringProperty(nameof(SumHeight), this.SumHeight.ToString());
            writer.WriteStringProperty(nameof(SumWidth), this.SumWidth.ToString());
        }
        public override void ReadProperties(ref JsonElement jele)
        {
            base.ReadProperties(ref jele);
            this.basePoint = jele.ReadVector2dProperty(nameof(BasePoint));
            string sumHeightProp = jele.ReadStringProperty(nameof(SumHeight));
            double.TryParse(sumHeightProp, out double hejght );
            this.SumHeight = hejght;
            string sumWidthProp = jele.ReadStringProperty(nameof(SumWidth));
            double.TryParse(sumWidthProp, out double width);
            this.SumWidth = width;
        }
    }
}